import { Layout, ParentLayout } from '@/router/constant'
import type { AppRouteRecordRaw } from '@/router/types'

const IFrame = () => import ('@/views/iframe/index.vue')

const LayoutMap = new Map<string, () => Promise<typeof import('*.vue')>>()

LayoutMap.set('Layout', Layout)
LayoutMap.set('Iframe', IFrame)


/**
 * 构建路由
 * 如果后端返回的路由格式不能直接用，可以在次做一些处理
 */
export const routerGenerator = (routerMap, parent?): any[] => {
  
  return routerMap.map((item: any) => {
    const currentRouter: any = {
      // 动态拼接路由地址。如/dashboard/workplace
      // path: `${(parent && parent.path) || ''}/${item.path}`,
      path: item.path,
      // 路由名称。必须唯一
      name: item.name || '',
      // 该路由对应的组件
      component: item.component,
      // 重定向地址
      redirect: item.redirect,
      hidden: item.hidden,
      // meta用来存放标题、菜单图标、页面权限
      meta: {
        ...item.meta,
        label: item.meta.title,
        permissions: null
      }
    }
    // 防止后端结果不规范时有可能拼接出两个反斜杠的问题
    currentRouter.path = currentRouter.path.replace('//', '/')

    // 若有子菜单，则递归处理
    if(item.children && item.children.length > 0) {

      // 若未定义redirect，默认第一个子路由为redirect
      !item.redirect && (currentRouter.redirect = `/${item.path}/${item.children[0].path}`)
      currentRouter.children = routerGenerator(item.children, currentRouter)
    }
    return currentRouter
  })
}


/**
 * 查找views目录中对应的组件文件
 */
let viewsModules: Record<string, () => Promise<Recordable>>
export const asyncImportRoute = (routes: AppRouteRecordRaw[] | undefined): void => {
  viewsModules = viewsModules || import.meta.glob('../views/**/*.vue')
  if(!routes) return
  routes.forEach((item) => {
    const { component, name, children } = item
    if(component) {

      const layoutFound = LayoutMap.get(component as string)
      if(layoutFound) {
        item.component = layoutFound
      } else {
        item.component = lazyImport(viewsModules, component as string);
      }
    } else if(name) {
      item.component = ParentLayout
    }
    children && asyncImportRoute(children)
  })
}


/**
 * 懒加载路由
 * @param viewModules views目录下扫描的全部集合
 * @param component 要找的组件，如 system/user/index
 * @returns 
 */
export const lazyImport = (
  viewModules: Record<string, () => Promise<Recordable>>,
  component: string
) => {
  
  const keys = Object.keys(viewModules)
  const matchKeys = keys.filter((key) => {
    let k = key.replace('../views/', '')
    const lastIndex = k.lastIndexOf('.')
    k = k.substring(0, lastIndex)
    return k === component
  })
  
  if(matchKeys?.length === 1) {
    const matchKey = matchKeys[0]
    return viewModules[matchKey]
  }
  if(matchKeys?.length > 1) {
    console.log("请不要在views目录下创建同名的文件夹或vue文件，这将导致动态导入失败")
    return
  }
}